package system

import (
	"gin-sns/app/dao/monitor/logininfor"
	"gin-sns/app/dao/monitor/online"
	"gin-sns/app/ginframe/response"
	"gin-sns/app/ginframe/utils/gconv"
	"gin-sns/app/ginframe/utils/ip"
	"gin-sns/app/model"

	logininforModel "gin-sns/app/model/monitor/logininfor"
	userOnlineModel "gin-sns/app/model/monitor/online"
	"gin-sns/app/service/monitor"
	"gin-sns/app/service/system"

	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/mojocn/base64Captcha"
	"github.com/mssola/user_agent"
)

type RegisterReq struct {
	UserName     string `form:"username"  binding:"required,min=5,max=30"`
	Password     string `form:"password" binding:"required,min=5,max=30"`
	ValidateCode string `form:"validateCode" binding:"required,min=4,max=10"`
	IdKey        string `form:"idkey" binding:"required,min=5,max=30"`
}

var LoginController = newLoginController()

func newLoginController() *loginController {
	return &loginController{}
}

type loginController struct {
}

// 登陆页面
func (c *loginController) Login(ctx *gin.Context) {

	if strings.EqualFold(ctx.Request.Header.Get("X-Requested-With"), "XMLHttpRequest") {
		response.ErrorResp(ctx).SetMsg("未登录或登录超时。请重新登录").WriteJsonExit()
		return
	}

	response.BuildTpl(ctx, "login").WriteTpl()
}

// 图形验证码
func (c *loginController) CaptchaImage(ctx *gin.Context) {
	//config struct for digits
	//数字验证码配置
	//var configD = base64Captcha.ConfigDigit{
	//	Height:     80,
	//	Width:      240,
	//	MaxSkew:    0.7,
	//	DotCount:   80,
	//	CaptchaLen: 5,
	//}
	//config struct for audio
	//声音验证码配置
	//var configA = base64Captcha.ConfigAudio{
	//	CaptchaLen: 6,
	//	Language:   "zh",
	//}
	//config struct for Character
	//字符,公式,验证码配置
	var configC = base64Captcha.ConfigCharacter{
		Height: 60,
		Width:  240,
		//const CaptchaModeNumber:数字,CaptchaModeAlphabet:字母,CaptchaModeArithmetic:算术,CaptchaModeNumberAlphabet:数字字母混合.
		Mode:               base64Captcha.CaptchaModeNumber,
		ComplexOfNoiseText: base64Captcha.CaptchaComplexLower,
		ComplexOfNoiseDot:  base64Captcha.CaptchaComplexLower,
		IsShowHollowLine:   false,
		IsShowNoiseDot:     false,
		IsShowNoiseText:    false,
		IsShowSlimeLine:    false,
		IsShowSineLine:     false,
		CaptchaLen:         6,
	}
	//创建声音验证码
	//GenerateCaptcha 第一个参数为空字符串,包会自动在服务器一个随机种子给你产生随机uiid.
	//idKeyA, capA := base64Captcha.GenerateCaptcha("", configA)
	//以base64编码
	//base64stringA := base64Captcha.CaptchaWriteToBase64Encoding(capA)
	//创建字符公式验证码.
	//GenerateCaptcha 第一个参数为空字符串,包会自动在服务器一个随机种子给你产生随机uiid.
	idKeyC, capC := base64Captcha.GenerateCaptcha("", configC)
	//以base64编码
	base64stringC := base64Captcha.CaptchaWriteToBase64Encoding(capC)
	//创建数字验证码.
	//GenerateCaptcha 第一个参数为空字符串,包会自动在服务器一个随机种子给你产生随机uiid.
	//idKeyD, capD := base64Captcha.GenerateCaptcha("", configD)
	//以base64编码
	//base64stringD := base64Captcha.CaptchaWriteToBase64Encoding(capD)
	ctx.JSON(http.StatusOK, model.CaptchaRes{
		Code:  0,
		IdKey: idKeyC,
		Data:  base64stringC,
		Msg:   "操作成功",
	})
}

//验证登陆
func (c *loginController) CheckLogin(ctx *gin.Context) {
	var req *RegisterReq
	//获取参数
	if err := ctx.ShouldBind(&req); err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}

	if req == nil {
		response.ErrorResp(ctx).SetMsg("用户名或密码错误").WriteJsonExit()
		return
	}

	//比对验证码
	verifyResult := base64Captcha.VerifyCaptcha(req.IdKey, req.ValidateCode)

	if !verifyResult {
		response.ErrorResp(ctx).SetMsg("验证码不正确").WriteJsonExit()
		return
	}

	isLock := monitor.LogininforService.CheckLock(req.UserName)

	if isLock {
		response.ErrorResp(ctx).SetMsg("账号已锁定，请30分钟后再试").WriteJsonExit()
		return
	}

	//验证账号密码
	if sessionId, err := system.UserService.SignIn(req.UserName, req.Password, ctx); err != nil {

		errTimes := monitor.LogininforService.SetPasswordCounts(req.UserName)

		having := 5 - errTimes

		//记录日志
		var info logininforModel.Entity
		info.LoginName = req.UserName
		info.Ipaddr = ctx.ClientIP()

		userAgent := ctx.Request.Header.Get("User-Agent")
		ua := user_agent.New(userAgent)
		info.Os = ua.OS()
		info.Browser, _ = ua.Browser()
		info.LoginTime = time.Now()
		info.LoginLocation = ip.GetCityByIp(info.Ipaddr)
		info.Msg = "账号或密码不正确"
		info.Status = "0"

		logininfor.LogininforDao.Insert(&info)

		response.ErrorResp(ctx).SetMsg("账号或密码不正确,还有" + gconv.String(having) + "次之后账号将锁定").WriteJsonExit()
	} else {
		//保存在线状态

		userAgent := ctx.Request.Header.Get("User-Agent")
		ua := user_agent.New(userAgent)
		os := ua.OS()
		browser, _ := ua.Browser()
		loginIp := ctx.ClientIP()
		loginLocation := ip.GetCityByIp(loginIp)

		var useronline userOnlineModel.Entity
		useronline.Sessionid = sessionId
		useronline.LoginName = req.UserName
		useronline.Browser = browser
		useronline.Os = os
		useronline.DeptName = ""
		useronline.ExpireTime = 1440
		useronline.Ipaddr = loginIp
		useronline.ExpireTime = 1440
		useronline.StartTimestamp = time.Now()
		useronline.LastAccessTime = time.Now()
		useronline.Status = "on_line"
		useronline.LoginLocation = loginLocation
		online.UserOnlineDao.Delete(&useronline)
		online.UserOnlineDao.Insert(&useronline)

		//移除登陆次数记录
		monitor.LogininforService.RemovePasswordCounts(req.UserName)
		//记录日志
		var info logininforModel.Entity
		info.LoginName = req.UserName
		info.Ipaddr = loginIp

		info.Os = os
		info.Browser = browser
		info.LoginTime = time.Now()
		info.LoginLocation = loginLocation
		info.Msg = "登陆成功"
		info.Status = "0"

		logininfor.LogininforDao.Insert(&info)
		response.SucessResp(ctx).SetMsg("登陆成功").WriteJsonExit()
	}
}
